home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 424_01 / ed_157 / parse_fnm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-23  |  12.0 KB  |  444 lines

  1. /*
  2.  * Copyright (C) 1992 by Rush Record
  3.  * Copyright (C) 1993 by Charles Sandmann (sandmann@clio.rice.edu)
  4.  * 
  5.  * This file is part of ED.
  6.  * 
  7.  * ED is free software; you can redistribute it and/or modify it under the terms
  8.  * of the GNU General Public License as published by the Free Software Foundation.
  9.  * 
  10.  * ED is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  11.  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  12.  * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  13.  * 
  14.  * You should have received a copy of the GNU General Public License along with ED
  15.  * (see the file COPYING).  If not, write to the Free Software Foundation, 675
  16.  * Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18. #include "opsys.h"
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23.  
  24. #include "rec.h"
  25. #include "window.h"
  26. #include "ed_dec.h"
  27. #include "buffer.h"
  28. #include "buf_dec.h"
  29. #include "ctyp_dec.h"
  30.  
  31. extern Char *filename();
  32.  
  33. static Char edityet = 0;
  34. static Char abortbuffer = 0;
  35. static Char specialskip = 0;    /* flags that no prompting must be done when files run out */
  36. static struct inhibit_flags
  37. {
  38.     unsigned int search:1;
  39.     unsigned int paste:1;
  40.     unsigned int line:1;
  41.     unsigned int word:1;
  42.     unsigned int chr:1;
  43. } inhibit;
  44.  
  45. /******************************************************************************\
  46. |Routine: insstr
  47. |Callby: parse_long_option parse_option
  48. |Purpose: Does what strstr() does, only case-insensitively.
  49. |Arguments:
  50. |    buf is the command line (which may contain upcase chars).
  51. |    str is the string we're looking for (which must be all lowercase).
  52. \******************************************************************************/
  53. Char *insstr(buf,str)
  54. Char *buf,*str;
  55. {
  56.     Char *p,*q,*r,c,d;
  57.     
  58.     for(p = buf,c = *str;(d = tolower(*p++));)
  59.         if(c == d)
  60.         {
  61.             for(q = p,r = str + 1;(d = *r++);)
  62.                 if(((Char)tolower(*q++)) != d)
  63.                     break;
  64.             if(!d)
  65.                 return(--p);
  66.         }
  67.     return(NULL);
  68. }
  69.     
  70. /******************************************************************************\
  71. |Routine: parse_option
  72. |Callby: parse_options
  73. |Purpose: Parses a simple option of the form -<character>.
  74. |         Returns a cleaned-up buffer, and 1 if -char is present, else 0.
  75. |Arguments:
  76. |    buf is the command line.
  77. |    chr is the <character> we're looking for.
  78. |    exact indicates (if nonzero) that the case is not to be ignored.
  79. \******************************************************************************/
  80. Int parse_option(buf,chr,exact)
  81. Char *buf;
  82. Int chr,exact;
  83. {
  84.     static Char str[5] = {' ','-',' ',' ',0};
  85.     static Char *localbuf = NULL;
  86.     static Int localbufsiz;
  87.     
  88.     Char *from,*to;
  89.     Int i,l;
  90.     
  91.     if((l = strlen(buf) + 3) > localbufsiz)
  92.     {
  93.         if(localbuf)
  94.             ifree(localbuf);
  95.         localbuf = (Char *)imalloc((localbufsiz = l));
  96.     }
  97.     str[2] = chr;
  98.     strcpy(localbuf," ");
  99.     strcat(localbuf,buf);
  100.     strcat(localbuf," ");
  101.     if(exact)
  102.     {
  103.         if(!(to = strstr(localbuf,str)))
  104.             return(0);
  105.     }
  106.     else
  107.         if(!(to = insstr(localbuf,str)))
  108.             return(0);
  109.     for(from = to + 3;(*to++ = *from++););
  110.     for(from = localbuf + 1,to = localbuf;(*to++ = *from++););    /* eliminate the preceeding space */
  111.     if((i = strlen(localbuf)) > 1)
  112.         localbuf[i - 1] = '\0';    /* trim trailing space */
  113.     strcpy(buf,localbuf);
  114.     return(1);
  115. }
  116.  
  117. /******************************************************************************\
  118. |Routine: parse_long_option
  119. |Callby: parse_options
  120. |Purpose: Parses an option of the form -<character><string>.
  121. |         Returns a cleaned-up buffer, and 1 if option is present, else 0.
  122. |Arguments:
  123. |    buf is the command line.
  124. |    chr is the <character> we're looking for.
  125. |    val is the returned <string>.
  126. \******************************************************************************/
  127. Int parse_long_option(buf,chr,val)
  128. Char *buf;
  129. Int chr;
  130. Char *val;
  131. {
  132.     static Char str[4] = {' ','-',' ',0};
  133.     static Char *localbuf = NULL;
  134.     static Int localbufsiz;
  135.     
  136.     Char *from,*to,*p,c;
  137.     Int i,l;
  138.     
  139.     if((l = strlen(buf) + 3) > localbufsiz)
  140.     {
  141.         if(localbuf)
  142.             ifree(localbuf);
  143.         localbuf = (Char *)imalloc((localbufsiz = l));
  144.     }
  145.     str[2] = chr;
  146.     strcpy(localbuf," ");
  147.     strcat(localbuf,buf);
  148.     strcat(localbuf," ");
  149.     if(!(to = insstr(localbuf,str)))
  150.         return(0);
  151.     for(p = val,from = to + 3;!isspace(c = *from++);*p++ = c);    /* copy the trailing value (possibly NULL) */
  152.     *p = '\0';
  153.     for(from--;(*to++ = *from++););
  154.     for(from = localbuf + 1,to = localbuf;(*to++ = *from++););    /* eliminate the preceeding space */
  155.     if((i = strlen(localbuf)) > 1)
  156.         localbuf[i - 1] = '\0';    /* trim trailing space */
  157.     strcpy(buf,localbuf);
  158.     return(1);
  159. }
  160.  
  161. /******************************************************************************\
  162. |Routine: parse_options
  163. |Callby: parse_filename
  164. |Purpose: Parses options out of the command line. Sets appropriate flags.
  165. |         Returns a cleaned-up buffer.
  166. |Arguments:
  167. |    file is the command line.
  168. |    recover is the recovery flag, set if -r is present.
  169. |    recfile is the journal file name (defaulted if absent).
  170. |    process is the text-processing flag, set if -t is present.
  171. |    multiple is the multiple-file-mode flag, set if -m is present.
  172. |    binary is the binary-mode flag, set to 1 if -b is present, 2 if -h.
  173. |    news is the flag that -n was present.
  174. \******************************************************************************/
  175. void parse_options(file,recover,recfile,process,multiple,binary,news)
  176. Char *file,*recover,*recfile,*process,*multiple,*binary,*news;
  177. {
  178.     Char *local;
  179.     Char *p;
  180.     Char buf[1024],buf2[1024];
  181.     Int l;
  182.     
  183. /* make a local copy with blank padding on both ends */
  184.     strcpy((local = (Char *)imalloc((l = strlen(file)) + 3)) + 1,file);
  185.     local[0] = ' ';
  186.     local[l + 1] = ' ';
  187.     local[l + 2] = '\0';
  188. /* check for -n, which overrides everything */
  189. #ifndef NO_NEWS
  190.     if(parse_option(local,'n',1))
  191.     {
  192.         *news = 1;
  193.         goto trim_servername;
  194.     }
  195.     else if(parse_option(local,'N',1))
  196.     {
  197.         *news = 2;
  198. trim_servername:
  199.         l = strlen(local);
  200.         local[--l] = '\0';            /* Trim trailing blank */
  201.         p = strrchr(local,' ') + 1;    /* Will always find leading blank */
  202.         while((*file++ = *p++));    /* Copy final parameter, stripping options */
  203.         return;
  204.     }
  205. #endif
  206.     *news = 0;
  207. /* turn -t into -r and set process flag */
  208.     if((p = insstr(local," -t ")))
  209.     {
  210.         *process = 1;
  211.         *(p + 2) = 'r';
  212.     }
  213.     else if((p = insstr(local," -t")))    /* NOTE! " -t" is not the same as " -t " */
  214.     {
  215.         *process = 1;
  216.         *(p + 2) = 'r';
  217.     }
  218.     if(parse_option(local,'u',0))
  219.         REPORTSTATUS = 1;
  220.     if(parse_option(local,'1',0))
  221.         specialskip = 2;
  222.     if(parse_long_option(local,'k',buf))
  223.         set_output_bak((strlen(buf))? buf : NULL);
  224.     if(parse_option(local,'m',0))
  225.         *multiple = 1;
  226.     if(parse_option(local,'b',0))
  227.         *binary = 1;
  228.     if(parse_option(local,'h',0))    /* -h takes precedence if both -b and -h are present */
  229.         *binary = 2;
  230.     if(parse_long_option(local,'f',buf))
  231.     {
  232.         strcpy(buf2,"-f");
  233.         strcat(buf2,buf);
  234.         file_list_init(buf2);
  235.     }
  236.     if(parse_long_option(local,'r',buf))
  237.     {
  238.         *recover = 1;
  239.         strcpy(recfile,(strlen(buf))? buf : (Char *)JOURNAL_FILE);
  240.     }
  241.     if(parse_long_option(local,'t',buf))
  242.     {
  243.         *process = 1;
  244.         strcpy(recfile,(strlen(buf))? buf : (Char *)JOURNAL_FILE);
  245.     }
  246.     if(parse_long_option(local,'i',buf))
  247.     {
  248.         my_sscanf(buf,"%d",&l);
  249.         if(l < 1)
  250.             l = 1;
  251.         edit_init_pos(l);
  252.     }
  253.     if(parse_long_option(local,'s',buf))
  254.     {
  255.         string_to_buf(buf,&SEARCHBUF);
  256.         inhibit.search = 1;
  257.     }
  258.     if(parse_long_option(local,'p',buf))
  259.     {
  260.         string_to_buf(buf,&KILLBUF);
  261.         inhibit.paste = 1;
  262.     }
  263.     if(parse_long_option(local,'l',buf))
  264.     {
  265.         string_to_buf(buf,&LINEBUF);
  266.         inhibit.line = 1;
  267.     }
  268.     if(parse_long_option(local,'w',buf))
  269.     {
  270.         string_to_buf(buf,&WORDBUF);
  271.         inhibit.word = 1;
  272.     }
  273.     if(parse_long_option(local,'c',buf))
  274.     {
  275.         string_to_buf(buf,&CHARBUF);
  276.         inhibit.chr = 1;
  277.     }
  278.     strcpy(file,local + 1);
  279.     if((l = strlen(file)))
  280.         file[l - 1] = '\0';
  281. }
  282.  
  283. /******************************************************************************\
  284. |Routine: parse_skip
  285. |Callby: command edit
  286. |Purpose: Flags that parse_fnm() must not prompt when files run out.
  287. |Arguments:
  288. |    flag is 0 or 1.
  289. \******************************************************************************/
  290. void parse_skip(flag)
  291. Int flag;
  292. {
  293.     specialskip = flag;
  294. }
  295.  
  296. /******************************************************************************\
  297. |Routine: strip_quotes
  298. |Callby: command init_term journal load_file main match_search parse_fnm wincom
  299. |Purpose: Strips quotes from quoted file names (in place).
  300. |Arguments:
  301. |    file is the file name.
  302. \******************************************************************************/
  303. void strip_quotes(file)
  304. Char *file;
  305. {
  306.     register Int i;
  307.     register Char *from,*to;
  308.     
  309.     from = to = file;
  310.     if(*from == '"')
  311.     {
  312.         i = strlen(from) - 1;
  313.         if(*(from + i) == '"' && *(from + i - 1) != '\\')
  314.         {
  315.             from = to + 1;
  316.             while(--i)
  317.                 if(*from == '\\' && *(from + 1) == '"')
  318.                 {
  319.                     *to++ = '"';
  320.                     from += 2;
  321.                     i--;    /* for the \ character */
  322.                 }
  323.                 else
  324.                     *to++ = *from++;
  325.             *to = '\0';
  326.         }
  327.     }
  328. }
  329.  
  330. /******************************************************************************\
  331. |Routine: parse_filename
  332. |Callby: edit main parse_fnm
  333. |Purpose: Handles parsing of command line options and file names
  334. |Arguments:
  335. |    command is the command line buffer. this is returned in a modified form.
  336. |    commlen is the length of the command buffer.
  337. |    editfile is the returned name of the file to be edited.
  338. |    recover is a flag indicating that we are in recovery mode, so edits come from the journal file.
  339. |    recfile is the returned name of the journal file from which edits are to be recovered.
  340. |    process is a flag indicating that we are in text processing mode, and must not prompt user.
  341. |    multiple is a flag indicating that -m was specified on the command line.
  342. |    binary is a flag indicating that -b or -h was specified on the command line.
  343. |    news is a flag indicating that -n was specified.
  344. \******************************************************************************/
  345. Int parse_filename(command,commlen,editfile,recover,recfile,process,multiple,binary,news)
  346. Char *command,*editfile,*recover,*recfile,*process,*multiple,*binary,*news;
  347. Int commlen;
  348. {
  349.     Char nextfile[512];
  350.  
  351. /* parse command line options */
  352. redo:
  353. /* handle ABORT command */
  354.     if(abortbuffer)    /* note, file_list_next will fail because command calls file_list_abort */
  355.     {
  356.         abortbuffer = 0;    /* make it a one-shot deal */
  357.         command[0] = '\0';    /* terminate parsing from buffer */
  358.     }
  359.     parse_options(command,recover,recfile,process,multiple,binary,news);
  360.     if(*news)
  361.     {
  362.         strcpy(editfile,command);
  363.         abortbuffer = 1;
  364.         edityet = 1;
  365.         return(1);
  366.     }
  367. /* see if more files are coming from list or wildcard */
  368. filelist:
  369.     if(file_list_next(nextfile))
  370.     {
  371.         parse_options(nextfile,recover,recfile,process,multiple,binary,news);    /* we allow options in file lists, alas */
  372.         strcpy(editfile,nextfile);
  373.         if(*recover)
  374.             unjournal_init(recfile,nextfile,&inhibit);    /* dump the file name that is in the journal file */
  375.         if(!edityet)
  376.         {
  377.             edityet = 1;
  378.             if(*process)
  379.             {
  380.                 putpurge();
  381.                 putoff();
  382.             }
  383.         }
  384.         return(1);
  385.     }
  386. /* see if more tokens are waiting in user buffer */
  387.     if(get_token(command,nextfile))
  388.     {
  389.         strip_quotes(nextfile);
  390.         file_list_init(nextfile);
  391.         goto filelist;
  392.     }
  393. /* nothing on command line, prompt if appropriate */
  394.     if(*process)
  395.         cleanup(0);
  396.     if(*recover)    /* they specified -r but no file, use file specified in journal file */
  397.     {
  398.         unjournal_init(recfile,editfile,&inhibit);    /* use the file name that is in the journal file */
  399.         return(1);
  400.     }
  401.     if(specialskip && edityet)
  402.     {
  403.         if(specialskip == 2)
  404.         {
  405.             move(NROW,1);
  406.             next();                /* Scroll up file name+lines */
  407.         }
  408.         specialskip = 0;
  409.         return(0);
  410.     }
  411. /* prompt them for a file name */
  412.     *process = *recover = *multiple = *binary = 0;
  413.     inhibit.search = inhibit.paste = inhibit.line = inhibit.word = inhibit.chr = 0;
  414.     marge(1,NROW);
  415.     move(NROW,1);
  416.     if(edityet)
  417.         next();
  418.     else
  419.         edityet = 1;
  420.     BOTROW = NROW;
  421.     if(inquire("File",command,commlen,1))
  422.     {
  423. #ifndef VMS
  424.         next();
  425. #endif
  426.         goto redo;
  427.     }
  428.     ers_end();
  429.     return(0);
  430. }
  431.  
  432. /******************************************************************************\
  433. |Routine: abort_parsing
  434. |Callby: command
  435. |Purpose: Aborts the taking of multiple filenames from the command line.
  436. |Arguments:
  437. |    none
  438. \******************************************************************************/
  439. void abort_parsing()
  440. {
  441.     abortbuffer = 1;
  442. }
  443.  
  444.